package tp.pr5.gui;

import java.util.ArrayList;
import java.util.Stack;

import tp.pr5.City;
import tp.pr5.Direction;
import tp.pr5.Place;
import tp.pr5.Street;
/**
 * Assigns the Places to the PlaceCells in the mapview
 * @author Mario
 *
 */
public class CityMapper {	
	private Stack<Place> pendientes;
	private ArrayList<Place> visitados;
	private City city;
	private MapView map;
	private static int initX = 5;
	private static int initY = 5;	
	public CityMapper(City city, MapView map){
		pendientes = new Stack<Place>();
		visitados = new ArrayList<Place>();
		this.city = city;
		this.map = map;
		
	}
	/**
	 * maps the place cells with Places
	 */
	public void map(){
		Place initialPlace = this.city.getInitialPlace();
		pendientes.push(initialPlace);
		int cellX = initX;
		int cellY = initY;
		map.getPlaceCell(cellX, cellY).setPlace(initialPlace);
		mapFromCell(map.getPlaceCell(cellX, cellY));
		
	}
	/**
	 * Returns true if the place is already visited
	 * @param pl
	 * @return
	 */
	private boolean isVisited(Place pl){
		for(int i=0;i< visitados.size();i++){
			Place crrnt = visitados.get(i);
			if(crrnt.equals(pl)){
				return true;
			}
		}
		
		return false;
	}
	/**
	 * Maps from the cell given
	 */
	private void mapFromCell(PlaceCell pc){
		/*
		 * Gets Places from the stack and adds them to the city map
		 */
		int cellX= pc.getXv();
		int cellY= pc.getYv();
		Place newPlace;
		while((!pendientes.empty()) && (newPlace = pendientes.pop()) != null){
						
			if(!isVisited(newPlace)){
				visitados.add(newPlace);
				/*
				 * Checks streets around the current place
				 */
				Street north = city.lookForStreet(newPlace, Direction.NORTH);
				if(north!=null){
					Place nextPlace = north.nextPlace(newPlace);
					if(!isVisited(nextPlace)){
						pendientes.push(nextPlace);	
						map.getPlaceCell(cellX, cellY-1).setPlace(nextPlace);
						
					}
				}
				Street south = city.lookForStreet(newPlace, Direction.SOUTH);
				if(south!=null){
					Place nextPlace = south.nextPlace(newPlace);
					if(!isVisited(nextPlace)){
						pendientes.push(nextPlace);					
						map.getPlaceCell(cellX, cellY+1).setPlace(nextPlace);
						
					}
				}
				Street west = city.lookForStreet(newPlace, Direction.WEST);
				if(west!=null){
					Place nextPlace = west.nextPlace(newPlace);
					if(!isVisited(nextPlace)){
						pendientes.push(nextPlace);	
						map.getPlaceCell(cellX-1, cellY).setPlace(nextPlace);
						
					}
				}
				Street east = city.lookForStreet(newPlace, Direction.EAST);
				if(east!=null){
					Place nextPlace = east.nextPlace(newPlace);
					if(!isVisited(nextPlace)){
						pendientes.push(nextPlace);	
						map.getPlaceCell(cellX+1, cellY).setPlace(nextPlace);
						
					}
				}
				/*
				 * maps from the discovered places
				 */
				if(east!=null)				mapFromCell(map.getPlaceCell(cellX+1, cellY));
				if(west!=null)				mapFromCell(map.getPlaceCell(cellX-1, cellY));
				if(south!=null) 			mapFromCell(map.getPlaceCell(cellX, cellY+1));
				if(north!=null)				mapFromCell(map.getPlaceCell(cellX, cellY-1));
				
			}
			
		}
	}
}
